﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using FFmpegVideoClip.Configuration;
using FFmpegVideoClip.Lib;
using FFmpegVideoClip.Lib.AdvancedFragmentProcessor;
using FFmpegVideoClip.Lib.AdvancedFragmentProcessor.InternalProcessor;

namespace FFmpegVideoClip.windows
{
    /// <summary>
    /// ConfigSetting.xaml 的交互逻辑
    /// </summary>
    public partial class ConfigSetting : Page
    {
        public MainWindow ParentWindow;
        private static int ClipSelect_SelectIndex, SelectPreset_SelectedIndex = 0;
        public ConfigSetting()
        {
            this.Loaded += (s, e) => ClipSelect.SelectedIndex = ClipSelect_SelectIndex < ClipSelect.Items.Count ? ClipSelect_SelectIndex : 0;
            InitializeComponent();
            ParentWindow = (MainWindow)Application.Current.MainWindow;
        }

        private void SettingOpenButton_Click(object sender, RoutedEventArgs e)
        {
            ProcessorSettings.ShowSettingsDialog();
        }

        private void ConfigSave_Button_Click(object sender, RoutedEventArgs e)
        {
            TimeWindowShow.ShowTimeDialog(Application.Current.MainWindow);
            Config.Save(Application.Current.MainWindow);
        }

        private void PresetSave_Button_Click(object sender, RoutedEventArgs e)
        {
            if (ClipSelect.SelectedIndex < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "尚无可保存的项", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            Clip clip = (Clip)ClipSelect.SelectedItem;

            if (PresetsList.SelectedIndex < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "未选择保存目标", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (MessageBoxEx.Show(Application.Current.MainWindow, "确认覆盖选项么？", "覆盖确认", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) == MessageBoxResult.Cancel)
                return;
            Preset preset = (Preset)PresetsList.SelectedItem;
            preset.SetFlows(clip.Flows, clip.AfterprocessingFlows);
        }

        private void PresetSaveAs_Button_Click(object sender, RoutedEventArgs e)
        {
            if (ClipSelect.SelectedIndex < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "未选择保存的项", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            Clip clip = (Clip)ClipSelect.SelectedItem;
            if (clip.Flows.Count < 1)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "尚无可保存的项", "保存错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (!InputTextWindow.ShowInputTextDialog(Application.Current.MainWindow, "预设名称", out string Result))
                return;
            if (string.IsNullOrEmpty(Result))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "名称非法", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (Config.Instance.Presets.Any(p => p.Name.Equals(Result, StringComparison.OrdinalIgnoreCase)))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "已存在相同项", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            Preset preset = new() { Name = Result };
            preset.SetFlows(clip.Flows, clip.AfterprocessingFlows);
            Config.Instance.Presets.Add(preset);
            ConfigSave_Button_Click(null!, null!);
        }

        private void ApplyPreset_Button_Click(object sender, RoutedEventArgs e)
        {
            if (ClipSelect.SelectedItems.Count < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "未选择设置目标", "操作错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            if (PresetsList.SelectedIndex < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "尚未选择要使用的配置", "操作错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            Preset preset;
            foreach (Clip clip in ClipSelect.SelectedItems)
            {
                preset = (Preset)PresetsList.SelectedItem;
                preset.SetTo(clip.Flows, clip.AfterprocessingFlows);
            }
        }

        private void ApplyPresetToAllClip_Button_Click(object sender, RoutedEventArgs e)
        {
            if (PresetsList.SelectedIndex < 0)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "尚未选择要使用的配置", "操作错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            MessageBoxResult SelectResult = MessageBoxEx.CustomButtonTextMessageBoxShow(Application.Current.MainWindow, "选择预设配置模式", "配置模式选择", MessageBoxButton.YesNoCancel, 
                MessageBoxImage.Question, MessageBoxResult.Cancel, null, "跳过已设置", "全部覆盖", "取消");
            if (SelectResult == MessageBoxResult.Cancel)
                return;
            Preset preset = (Preset)PresetsList.SelectedItem;
            foreach (Clip clip in ClipManage.ClipList.Where(p => !p.IsUIFreeze))
            {
                if (SelectResult == MessageBoxResult.No)
                    preset.SetTo(clip.Flows, clip.AfterprocessingFlows);
                else if (clip.Flows.Count < 1)
                    preset.SetTo(clip.Flows, clip.AfterprocessingFlows);
            }
        }

        private void OpenFlowSelect(object sender, RoutedEventArgs e) => FlowSelect.ShowWindow();

        private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;
                if (((Control)sender).Parent is UIElement parent)
                    parent.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = MouseWheelEvent, Source = sender });
            }
        }

        private void ClosePage_Button_Click(object sender, RoutedEventArgs e)
        {
            //MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left); 
            //args.RoutedEvent = Button.ClickEvent; 
            ParentWindow?.CloseSub.RaiseEvent(e);
        }
        
        private void SelectPreset_Loaded(object sender, RoutedEventArgs e)
        {
            if (Config.Instance.Presets.Count > 0)
                ((ListBox)sender).SelectedIndex = SelectPreset_SelectedIndex;
        }
        //private void InputSelect_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        //{
        //    if (e.AddedItems.Count < 1 || e.AddedItems[0] is not AdvancedParametersSchemeModule module)
        //        return;
        //    if (module == AdvancedParametersSchemeModule.ComboBoxSelectSourceUIItem)
        //        ((ComboBox)sender).SelectedIndex = -1;
        //}

        //输入参数中，关掉自己的可选项
        private void FlowSelect_ComboBox_DropDownOpened(object sender, EventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            FrameworkElement fe;
            AdvancedParametersSchemeModule CurrentModule;

            fe = (FrameworkElement)VisualTreeHelper.GetParent(cb);

            while (fe!.DataContext is not AdvancedParametersSchemeModule)
            {
                fe = (FrameworkElement)VisualTreeHelper.GetParent(fe);
            }
            CurrentModule = (AdvancedParametersSchemeModule)fe.DataContext;

            AdvancedParametersSchemeModule module = cb.Items.Cast<AdvancedParametersSchemeModule>().First(p => p == CurrentModule);

            Task.Run(() =>
            {
                Thread.Sleep(500);
                cb.Dispatcher.BeginInvoke(() =>
                {
                    ((ComboBoxItem)cb.ItemContainerGenerator.ContainerFromItem(module)).IsEnabled = false;
                });

            });
        }

        private void ShowLog_Button_Click(object sender, RoutedEventArgs e)
        {
            LogInfoWindow.ShowLogInfo();
        }

        #region List拖动排序
        private void FlowsListDrop_TextBlock_PreviewMouseMove(object sender, MouseEventArgs e) => Tools.ObservableCollection_DropMove<ListBox, AdvancedParametersSchemeModule>(sender, e, DragDropEffects.Copy);
        private void Preset_MouseMove(object sender, MouseEventArgs e) => Tools.ObservableCollection_DropMove<ListBox, Preset>(sender, e, DragDropEffects.Move);
        private void FlowsList_PreviewDrop(object sender, DragEventArgs e)
        {
            ListBox listBox = (ListBox)sender;
            if (ClipSelect.SelectedItem is not Clip m_clip)
                return;
            Tools.ObservableCollection_Drop<ListBoxItem, AdvancedParametersSchemeModule>(sender, e, listBox.Name.Equals("AfterprocessingFlowsList", StringComparison.OrdinalIgnoreCase) ? m_clip.AfterprocessingFlows : m_clip.Flows, DragDropEffects.Copy, true);
        }
        private void Preset_Drop(object sender, DragEventArgs e) => Tools.ObservableCollection_Drop<ListBoxItem, Preset>(sender, e, Config.Instance.Presets, DragDropEffects.Move, false);
        #endregion

        private void ClipSelect_SelectionChanged(object sender, SelectionChangedEventArgs e) { ClipSelect_SelectIndex = ClipSelect.SelectedIndex;}

        private void CopyCommand(Clip clip,AdvancedParametersSchemeModule SelectModule)
        {
            AdvancedParametersSchemeModule module = SelectModule.DeepCopy();
            
            if( clip.Fragments.Count >0 )
                module.GetInput().Parameter =  clip.Fragments[0].InputPath;    
            else module.GetInput().Parameter = "InputNull";

            module.GetOutput().Parameter = $"Out[{module.SchemeName}].{module.GetOutput().Parameter}";

            if(module.GetParametersSign(ParametersSign.STime,out ParametersSign? StartTime))
                StartTime!.Parameter = clip.Fragments[0].StartTimeValue;

            if(module.GetParametersSign(ParametersSign.ETime,out ParametersSign? EndTime))
                EndTime!.Parameter = clip.Fragments[0].EndTimeValue;

            CallProcessor callProcessor= module.GetCallProcessor();

            if(StartTime != null && EndTime != null && module.DurationMode && callProcessor.DurationMode)
            {
                TimeSpan st= Tools.GetStringTimeToTimeSpan(StartTime.Parameter);
                TimeSpan et= Tools.GetStringTimeToTimeSpan(EndTime.Parameter);
                EndTime.Parameter = Tools.GetTimeSpanToString_Digit(et - st);
            }
            CallShell.ShellTypeProcessNameIFSet(module);
            System.Windows.Forms.Clipboard.SetText($"{module.GetCallProcessor().ProcessorName} {module.GenerateCommandArgument()}", System.Windows.Forms.TextDataFormat.Text);
            //Clipboard.SetText($"{module.GetCallProcessor().ProcessorName} {module.GenerateCommandArgument()}");

        }

        private void MenuItem_DeleteFlow_Click(object sender, RoutedEventArgs e)
        {

            if (sender is not MenuItem menuItem)
                return;
            if (menuItem.Parent is not ContextMenu cm)
                return;
            if (ContextMenuService.GetPlacementTarget(cm) is not FrameworkElement fe || fe.DataContext is not AdvancedParametersSchemeModule SelectModule)
                return;

            switch (menuItem.Tag)
            {
                case "DeleteFlows":
                    if (Tools.GetParent<ListBox>(fe, out ListBox? listBox))
                        ((ObservableCollection<AdvancedParametersSchemeModule>)listBox!.ItemsSource).Remove(SelectModule);
                    return;
                case "CopyCommand":
                   CopyCommand((Clip)ClipSelect.SelectedItem,SelectModule);
                    return;                    
                default:
                    return;
            }
        }

        private void SelectPreset_SelectionChanged(object sender, SelectionChangedEventArgs e) { SelectPreset_SelectedIndex = PresetsList.SelectedIndex; }

        private void RunButtonMenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = (MenuItem)sender;
            switch (menuItem.Tag)
            {
                case "QueueTasks":
                    QueueTasksButton_Click();
                    return;
                case "AutoMix":
                    AutoMixButton_Click();
                    return;
                default: AllRunButton_Click(); return;
            }
        }

        private void RunButton_Click(object sender, RoutedEventArgs e)
        {
            ContextMenu menu = (ContextMenu)this.Resources["RunButtonContextMenu"];
            menu.IsOpen = true;
        }
        private void AllRunButton_Click()
        {
            if (ClipManage.TotalFragmentCount < 1)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, $"没有片段信息", "操作错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            StringBuilder sb = new StringBuilder();
            foreach (Clip clip in ClipManage.ClipList)
            {
                if (!Tools.CheckFlowsParameter(clip.Flows, out string info))
                {
                    sb.AppendLine($"剪辑[{clip.Name}]");
                    sb.AppendLine(info);
                }
            }
            if (sb.Length > 1)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, sb.ToString(), "未赋值的参数", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            AdvancedTaskFlowManage.StartUP();
        }

        private void AutoMixButton_Click()
        {
            if (ClipManage.TotalFragmentCount < 1)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, $"没有片段信息", "操作错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            StringBuilder sb = new StringBuilder();
            foreach (Clip clip in ClipManage.ClipList)
            {
                if (!Tools.CheckFlowsParameter(clip.Flows, out string info))
                {
                    sb.AppendLine($"剪辑[{clip.Name}]");
                    sb.AppendLine(info);
                }
            }
            if (sb.Length > 1)
            {
                MessageBoxEx.Show(Application.Current.MainWindow, sb.ToString(), "未赋值的参数", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            AudioMix.StartUP();
        }

        private async void QueueTaskCancellationButton_Click(object sender, RoutedEventArgs e)
        {
            Clip clip = (Clip)((Button)sender).DataContext;
            clip.IsCanceling = true;
            await Task.Run(() => QueueTasksMagage.QueueTaskCancel(clip));
            clip.IsCanceling = false;
        }

        private async void AddQueueTaskButton_Click(object sender, RoutedEventArgs e)
        {
            Clip clip = (Clip)((Button)sender).DataContext;
            await Task.Run(() => QueueTasksMagage.PushTask(clip));
        }

        private void QueueTasksButton_Click()
        {
            MainWindow window = (MainWindow)Application.Current.MainWindow;
            QueueTasksMagage.QueueStart(new UIElement[] { window.AllOutButton, window.FileModeButton, window.ConfigSettingButton, window.SettingButton, window.ClearClipsButton, window.CleanCacheButton, ExecuteButton });
        }

        private void MenuItem_Preset_Click(object sender, RoutedEventArgs e)
        {
            if (sender is not MenuItem menuItem)
                return;
            if (menuItem.Parent is not ContextMenu cm)
                return;
            if (ContextMenuService.GetPlacementTarget(cm) is not FrameworkElement fe || fe.DataContext is not Preset SelectPreset)
                return;

            switch (menuItem.Tag)
            {
                case "Splitted":
                    AddPresetSplitted(SelectPreset);
                    return;
                case "Rename":
                    PresetRename(SelectPreset);
                    return;
                case "Delete":
                    Config.Instance.Presets.Remove(SelectPreset);
                    Config.Save();
                    return;
                default:
                    return;
            }
        }
        private void AddPresetSplitted(Preset SelectPreset)
        {
            if (SelectPreset == null || !Config.Instance.Presets.Contains(SelectPreset))
            {
                LogManage.WriteLineNewInfo($"Preset:[{SelectPreset?.Name ?? string.Empty}] 重命名错误", true);
                return;
            }

            if (!InputTextWindow.ShowInputTextDialog(Application.Current.MainWindow, "预设名称", out string Result))
                return;
            if (string.IsNullOrEmpty(Result))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "名称非法", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (Config.Instance.Presets.Any(p => p.Name.Equals(Result, StringComparison.OrdinalIgnoreCase)))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "已存在相同项", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            Preset preset = new Preset();
            preset.IsSplittedTitle = true;
            preset.Name=Result;
            Config.Instance.Presets.Insert(Config.Instance.Presets.IndexOf(SelectPreset), preset);
            Config.Save();
        }
        private void PresetRename(Preset? preset)
        {
            if (preset == null || !Config.Instance.Presets.Contains(preset))
            {
                LogManage.WriteLineNewInfo($"Preset:[{preset?.Name ?? string.Empty}] 重命名错误", true);
                return;
            }

            if (!InputTextWindow.ShowInputTextDialog(Application.Current.MainWindow, "预设名称", out string Result, preset.Name))
                return;
            if (string.IsNullOrEmpty(Result))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "名称非法", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (Config.Instance.Presets.Any(p => p.Name.Equals(Result, StringComparison.OrdinalIgnoreCase)))
            {
                MessageBoxEx.Show(Application.Current.MainWindow, "已存在相同项", "名称错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            preset.Name = Result;
            Config.Save();
        }
    }
}
